package com.noble.meether.chat.ui.agora.util;

import android.support.v4.app.FragmentActivity;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.faceunity.MRender;
import com.noble.glamour.module.logic.application.App;
import com.noble.glamour.module.logic.application.ModuleMgr;
import com.noble.glamour.module.logic.baseui.LoadingDialog;
import com.noble.glamour.module.logic.request.RequestComplete;
import com.noble.glamour.module.util.TimerUtil;
import com.noble.glamour.ui.utils.CheckIntervalTimeUtil;
import com.noble.library.log.PToast;
import com.noble.library.observe.MsgMgr;
import com.noble.library.observe.MsgType;
import com.noble.meether.R;
import com.noble.meether.chat.ui.agora.RtcUIShow;
import com.noble.meether.chat.ui.agora.act.bean.ChatStatus;
import com.noble.meether.chat.ui.agora.model.AGEventHandler;
import com.noble.meether.chat.ui.agora.model.AgoraConstant;
import com.noble.meether.chat.ui.agora.model.EngineConfig;
import com.noble.meether.chat.unread.UnreadMgr;

import io.agora.rtc.Constants;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;

/**
 * 抽取音视频连接控制和流控制逻辑到该类:  方便实现悬浮窗功能
 * <p>
 * Created by Su on 2017/7/12.
 */
public class RtcJointChannel {
    private static RtcJointChannel mInstance;
    private CheckIntervalTimeUtil checkIntervalTimeUtil;  // 时间监测

    private boolean isFloating = false;    // 是否处于悬浮窗状态

    public static RtcJointChannel getInstance() {
        if (mInstance == null)
            mInstance = new RtcJointChannel();
        return mInstance;
    }

    private RtcJointChannel() {
        checkIntervalTimeUtil = new CheckIntervalTimeUtil();
    }

    public void setFloatStatus(boolean isFloating) {
        this.isFloating = isFloating;
    }

    public boolean getFloatStatus() {
        return isFloating;
    }

    private EngineConfig config() {
        return ModuleMgr.getRtcEnginMgr().getEngineConfig();
    }

    //===================================== Agora连接控制流控制 ====================================

    private boolean isFirstVideo = true;

    public void setFirstVideo(boolean first) {
        this.isFirstVideo = first;
    }

    public boolean getFirstVideo() {
        return isFirstVideo;
    }

    /**
     * 加入频道
     *
     * @param isLoading true 展示加入进度条
     */
    public void joinChannelPrepare(boolean isLoading) {
        if (isLoading) {
            LoadingDialog.show((FragmentActivity) App.activity, App.activity.getString(R.string.joining_chat));
        }
        // 视频聊天初始化
        if (ModuleMgr.getRtcEnginMgr().getEngineConfig().mChatType == AgoraConstant.RTC_CHAT_VIDEO) {
            isFirstVideo = true;
            MRender.create(App.context);
            ModuleMgr.getRtcEnginMgr().configVideoEngine(Constants.VIDEO_PROFILE_720P, null, null);
            ModuleMgr.getRtcEnginMgr().getRtcEngine().enableVideo();
            resetAudioMute();
        } else { // 音频聊天初始化
            ModuleMgr.getRtcEnginMgr().getRtcEngine().enableAudio();
            ModuleMgr.getRtcEnginMgr().switchMicro(true);
        }

        RtcTimerUtil.getInstance().stopStatisInvTime();      // 关闭邀请计时
        RtcTimerUtil.getInstance().startStatisChatTime();    // 开始通信时长统计
        ModuleMgr.getRtcEnginMgr().addEventHandler(handler);
    }

    /**
     * 用户离线
     */
    public void userOffline() {
        RtcUtil.getInstance().setHangUp();  // 收到用户音视频聊天已经挂断消息
        config().mJoinStatus = false;
        App.activity.runOnUiThread(() -> {
            MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Close_Msg, null);
            RtcUIShow.showRtcCommentAct(App.activity, config().mOtherId);
        });
    }

    public void reqChatStart() {
        if (ModuleMgr.getCenterMgr().getMyInfo().isMan()) {  // 男方进行检测：因为男方需要处理倒计时逻辑
            ModuleMgr.getRtcChatMgr().reqChatStart(config().mVcid, config().mOtherId, response -> {
                if (response.isOk()) {
                    RtcSubUtil.getInstance().startVideoChatTime();  // 接通后开启轮询付费信息

                    ChatStatus chatStatus = (ChatStatus) response.getBaseData();
                    ModuleMgr.getCenterMgr().getMyInfo().setDiamand(chatStatus.getDoLeave());
                    RtcSubUtil.getInstance().showCountView(chatStatus.getSecondLeave());
                    return;
                }
                PToast.showShort("本次通话已关闭");
                ModuleMgr.getRtcChatMgr().sendHangUpMsg(null);
                MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Close_Msg, null);
            });
        }
    }

    /**
     * 通信状态回调
     */
    public AGEventHandler handler = new AGEventHandler() {
        @Override
        public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
            config().mJoinStatus = true;
            UnreadMgr.whisperId = config().mOtherId;
            MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Connect_Suc, null);
            reqChatStart();
        }

        @Override
        public void onUserOffline(int uid, int reason) {
        }

        @Override
        public void onConnectionLost() {
            App.activity.runOnUiThread(() -> PToast.showShort(App.activity.getString(R.string.chat_audio_conn_fail)));
            stopChat();
        }

        @Override
        public void onConnectionInterrupted() {
            badNetTips();
        }

        @Override
        public void onLastmileQuality(int quality) {
            if (quality >= AgoraConstant.QUALITY_BAD)
                badNetTips();
        }

        @Override
        public void onNetworkQuality(int uid, int txQuality, int rxQuality) {
            if (txQuality >= AgoraConstant.QUALITY_BAD || rxQuality >= AgoraConstant.QUALITY_BAD)
                badNetTips();
        }

        // -------------- 视频相关回调 -------------------------
        @Override
        public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
            ModuleMgr.getRtcEnginMgr().getEngineConfig().mOpenCamera = true;
            ModuleMgr.getRtcEnginMgr().getRtcEngine().setupRemoteVideo(new VideoCanvas(getRemoteSurfaceV(), VideoCanvas.RENDER_MODE_HIDDEN, uid));
            MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Video_Remote, uid);
        }

        @Override
        public void onUserMuteVideo(int uid, boolean muted) {
            // 女用户： 对方每次改变视频开关状态回调该方法
            ModuleMgr.getRtcEnginMgr().getEngineConfig().mOpenCamera = !muted;
            MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Remote_Status, muted);
        }
    };

    /**
     * 弱网提示
     */
    private void badNetTips() {
        App.activity.runOnUiThread(() -> {
            if (checkIntervalTimeUtil == null) return;
            if (checkIntervalTimeUtil.check(AgoraConstant.CHECK_INTERVAL)) {
                PToast.showCenterLong(App.activity.getString(R.string.net_bad));
            }
        });
    }

    /**
     * 语音路由切换
     */
    private boolean switchMicro = true;    // 语音路由切换标志: true 外放  false 听筒

    public void switchMicro() {
        switchMicro = !switchMicro;
        ModuleMgr.getRtcEnginMgr().setEnableSpeakerphone(switchMicro);
        ModuleMgr.getRtcEnginMgr().switchMicro(switchMicro);
        MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Switch_Micro, switchMicro);
    }

    public boolean getSwitchMicro() {
        return switchMicro;
    }

    public void resetSwitchMicro() {
        switchMicro = true;
    }

    /**
     * 视频静音状态切换
     */
    private boolean isMute = false;  // 麦克风状态切换

    public void switchAudio() {
        ModuleMgr.getRtcEnginMgr().switchLocalAudioStream(!isMute);
        isMute = !isMute;
    }

    private void resetAudioMute() {
        isMute = false;
    }

    public boolean getSwitchAudio() {
        return isMute;
    }

    /**
     * 摄像头切换
     */
    private boolean switchCamera = false;   // 摄像头切换标志

    public boolean getSwitchCamera() {
        return switchCamera;
    }

    public void switchCamera() {
        ModuleMgr.getRtcEnginMgr().switchCamera();
        if (switchCamera) {
            switchCamera = false;
            return;
        }
        switchCamera = true;
    }


    // ========================================= 视频相关 =======================================
    private SurfaceView remoteSurfaceV;     // 远端视频控件
    private SurfaceView localSurfaceV;      // 本地视频控件
    private FrameLayout remoteContainer;    // 远端容器
    private FrameLayout localContainer;     // 本地容器

    public void setVideoContainer(FrameLayout remoteContainer, FrameLayout localContainer) {
        this.remoteContainer = remoteContainer;
        this.localContainer = localContainer;
    }

    /**
     * 远端视频加载器
     */
    public SurfaceView getRemoteSurfaceV() {
        if (remoteSurfaceV == null) {
            remoteSurfaceV = RtcEngine.CreateRendererView(App.activity.getApplicationContext());
            remoteSurfaceV.setZOrderOnTop(false);
            remoteSurfaceV.setZOrderMediaOverlay(false);
        }
        return remoteSurfaceV;
    }

    /**
     * 本地视频加载器
     */
    public SurfaceView getLocalSurfaceV() {
        if (localSurfaceV == null) {
            localSurfaceV = RtcEngine.CreateRendererView(App.activity.getApplicationContext());
            localSurfaceV.setZOrderOnTop(false);
            localSurfaceV.setZOrderMediaOverlay(false);
        }
        return localSurfaceV;
    }

    /**
     * 绑定双方视频到容器
     */
    public void initSurfaceV() {
        removeLocalView();
        removeRemoteView();
        remoteContainer.addView(localSurfaceV);
        localContainer.addView(remoteSurfaceV);

        TimerUtil.beginTime(this::switchVideo, 50);
    }

    /**
     * 绑定远端视频到远端容器
     */
    public void setRemoteToRemote() {
        removeRemoteView();
        remoteContainer.removeAllViews();
        remoteContainer.addView(remoteSurfaceV);
        RtcSubUtil.getInstance().setCaptureView(remoteContainer);
    }

    /**
     * 绑定本地视频到远端容器
     */
    public void setLocalToRemote() {
        removeLocalView();
        remoteContainer.removeAllViews();
        remoteContainer.addView(localSurfaceV);
    }

    /**
     * SurfaceV移除
     */
    public void removeRemoteView() {
        if (remoteSurfaceV != null && remoteSurfaceV.getParent() != null) {
            ((ViewGroup) remoteSurfaceV.getParent()).removeView(remoteSurfaceV);
        }
    }

    public void removeLocalView() {
        if (localSurfaceV != null && localSurfaceV.getParent() != null)
            ((ViewGroup) localSurfaceV.getParent()).removeView(localSurfaceV);
    }

    /**
     * 视频大小窗切换
     */
    private boolean switchVideo = false;    // 视频切换标志

    public void setSwitchVideo(boolean switchVideo) {
        this.switchVideo = switchVideo;
    }

    public boolean getSwitchVideo() {
        return switchVideo;
    }

    public void switchVideo() {
        remoteContainer.removeAllViews();
        localContainer.removeAllViews();

        if (switchVideo) {  // 已经切换
            switchVideo = false;
            removeLocalView();
            removeRemoteView();
            localContainer.addView(localSurfaceV);
            remoteContainer.addView(remoteSurfaceV);
            RtcSubUtil.getInstance().setCaptureView(remoteContainer);
            return;
        }
        switchVideo = true;
        removeLocalView();
        removeRemoteView();
        localContainer.addView(remoteSurfaceV);
        remoteContainer.addView(localSurfaceV);
        RtcSubUtil.getInstance().setCaptureView(localContainer);
    }

    /**
     * View XML创建，因持有Activity的context需手动回收
     */
    public void releaseView() {
        if (remoteContainer != null)
            remoteContainer.removeAllViews();
        if (localContainer != null)
            localContainer.removeAllViews();
        removeLocalView();
        removeRemoteView();

        remoteContainer = null;
        remoteSurfaceV = null;
        localContainer = null;
        localSurfaceV = null;

    }

    // =============================== 服务器接口调用 ==============================================
    public void reqUserInfo(RequestComplete complete) {
        ModuleMgr.getCenterMgr().reqOtherInfo(config().mOtherId, complete);
    }

    /**
     * 挂断
     */
    public void stopChat() {
        config().mJoinStatus = false;
        ModuleMgr.getRtcChatMgr().sendHangUpMsg(null);
        MsgMgr.getInstance().sendMsg(MsgType.MT_Rtc_Chat_Close_Msg, null);
        ModuleMgr.getRtcEnginMgr().releaseLocalPoll();
        ModuleMgr.getRtcChatMgr().reqStopVideoChat(config().mVcid, response -> RtcUIShow.showRtcCommentAct(App.activity, config().mOtherId));
        ModuleMgr.getRtcEnginMgr().leaveChannel(config().mChannel);
        PToast.showShort("通话结束");
    }

    /**
     * 被邀请方接受
     */
    public void acceptChat(RequestComplete complete) {
        LoadingDialog.show((FragmentActivity) App.activity, App.activity.getString(R.string.joining_chat));
        ModuleMgr.getRtcChatMgr().reqAcceptVideoChat(config().mOtherId, config().mChatType, complete);
    }
}
